# KNN处理约会对象数据
import numpy as np
import operator as op


# 把文本数据转换成numpy对象
def file2matrix(filename):
    fr=open(filename)

    # 获取文件的行数
    arrayOLines=fr.readlines()


    # 创建返回的numpy返回矩阵对象
    numberOLines=len(arrayOLines)
    returnMat=np.zeros((numberOLines,3))
    classLabelVector=[]
    index=0
    for line in arrayOLines:
        # 解析文件数据到列表
        line=line.strip()    # 去掉txt中的  \n字段
        listFromLine=line.split(' ')
        returnMat[index,:]=listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index+=1
    return returnMat,classLabelVector

# 归一化处理
def autoNorm(dataset):
    minVals=dataset.min(0)
    maxVals=dataset.max(0)
    ranges=maxVals-minVals
    normDataset=np.zeros(np.shape(dataset))
    m=dataset.shape[0]
    normDataset=dataset-np.tile(minVals,(m,1))
    # 特征值相除
    normDataset=normDataset/np.tile(ranges,(m,1))
    return normDataset,ranges,minVals

def classify0(inX,dataset,labels,k):
    datasetSize=dataset.shape[0]

    # 计算距离
    diffMat=np.tile(inX,(datasetSize,1))-dataset
    sqDiffMat=diffMat**2
    sqDistances=sqDiffMat.sum(axis=1)
    distances=sqDistances**0.5

    # 
    sortedDistIndicies=distances.argsort()
    classCount={}
    for i in range(k):
        voteIlabel=labels[sortedDistIndicies[i]]
        # 选择距离最小的点
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1

    # 排序
    sortedClassConut=sorted(classCount.items(),key=op.itemgetter(1),reverse=True)
    return sortedClassConut[0][0]

# 分类器
def datingClassTest():
    hoRatio=0.10
    datingDataMat,datingLabels=file2matrix('C:/Users/cchyp/Desktop/numpy/datingTestSet.txt')
    normMat,ranges,minVals=autoNorm(datingDataMat)
    m=normMat.shape[0]
    print(m)
    numTestVecs=int(m*hoRatio)
    errorCount=0.0
    for i in range(numTestVecs):
        classifierResult=classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        print('结果 : ',classifierResult)
    if numTestVecs:
        # 伪造的数据没有识别出来，所以结果没有打印 
        print('误差率 : ',(errorCount/float(numTestVecs)))

datingClassTest()